package com.learning.thread.base.comunication;

/**
 * ClassName: ThreadCommunication
 * Description: 线程同步: 实现多线程交互，需要配合使用Synchronized 和 Object对象的`wait`、`notify` 方法
 * 关键字：wait、notify、一个boolean类型参数。
 * <p>
 * 通过一个简单的案例实现线程通信：两个线程：
 * 子线程循环5次，主线程循环5次，然后子线程又循环3次，主线程10次，如此一共循环2次。
 * Date: 2016/11/26 17:03
 *
 * @author SAM SHO
 * @version V1.0
 */
public class ThreadCommunication {

    public static void main(String[] args) {
        Data data = new Data();
        new Thread(new MainThread(data), "thead 0 ").start();
        new Thread(new SubThread(data), "thead 1 ").start();
    }


    /**
     * 主线程
     */
    static class MainThread implements Runnable {

        private Data data;

        public MainThread(Data data) {
            this.data = data;
        }

        @Override
        public void run() {
            try {
                for (int i = 0; i < 2; i++) {
                    data.mainMethod();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 子线程
     */
    static class SubThread implements Runnable {

        private Data data;

        public SubThread(Data data) {
            this.data = data;
        }

        @Override
        public void run() {
            try {
                for (int i = 0; i < 2; i++) {
                    data.subMethod();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 业务对象
     */
    static class Data {
        /**
         * 默认子线程运行
         */
        private volatile boolean isSubRunnable = true;

        synchronized void mainMethod() throws InterruptedException {

            // 主线程先等待
            while (isSubRunnable) {
                this.wait();
            }


            for (int i = 0; i < 5; i++) {
                System.out.println("Main线程运行次数 ： " + i);
            }


            isSubRunnable = true;
            this.notify();
        }

        synchronized void subMethod() throws InterruptedException {

            // 一开始是true,先子线程运行
            while (!isSubRunnable) {
                this.wait();
            }

            for (int i = 0; i < 3; i++) {
                System.out.println("Sub线程运行次数 ： " + i);
            }

            isSubRunnable = false;
            this.notify();//唤醒
        }

    }


}
